#include <thread_intf.h>
#include <lvos.h>
#include "log_intf.h"
#include "co_routine.h"
#include "semaphore.h"

#if DESC("协程")
typedef struct TagLwtContext {
    void (*func)(void *ctx);
    void *ctx;
} LwtContext;

void LwtSleep(uint32_t ms)
{
    poll(NULL, 0, ms);
}

void *LwtFunc(void *context)
{
    co_enable_hook_sys();
    LwtContext *lwtCtx = (LwtContext *)context;
    void (*func)(void *ctx) = lwtCtx->func;
    void *ctx = lwtCtx->ctx;
    delete(lwtCtx);
    func(ctx);
    return NULL;
}

int32_t LwtCreate(void (*func)(void *ctx), void *ctx, const char *funcName, int32_t line)
{
    LwtContext *lwtCtx = new LwtContext;
    lwtCtx->ctx = ctx;
    lwtCtx->func = func;
    stCoRoutine_t *routine = NULL;
    co_create(&routine, NULL, LwtFunc, lwtCtx);
    co_resume(routine);
    return RETURN_OK;
}

void LwtStartEventLoop(void)
{
    co_eventloop(co_get_epoll_ct(), NULL, NULL);
}

bool IsLwtContext(void)
{
    return (co_self() != NULL);
}

int32_t LwtModuleInit(void)
{
    return RETURN_OK;
}

#endif

#if DESC("信号量")

int32_t InitSyncContext(SyncContext *syncContext)
{
    syncContext->lwtSem = NULL;
    syncContext->pThreadSem = NULL;
    if (IsLwtContext()) {
        struct stCoCond_t *coCond = co_cond_alloc();
        if(coCond == NULL) {
            return RETURN_ERROR;
        }
        syncContext->lwtSem = coCond;
        printf("123\n");
    } else {
        sem_t *sem = (sem_t *)malloc(sizeof(sem_t));
        int ret = sem_init(sem, 0, 0);
        if (ret != RETURN_OK) {
            free(sem);
            return RETURN_ERROR;
        }
        printf("456\n");
        syncContext->pThreadSem = sem;
    }
    return RETURN_OK;
}

void WaitSyncContext(SyncContext *syncContext)
{
    if (syncContext->pThreadSem == NULL) {
        co_cond_timedwait((struct stCoCond_t *)syncContext->lwtSem, -1);
    } else {
        sem_wait((sem_t *)syncContext->pThreadSem);
    }
}

void DestroySyncContext(SyncContext *syncContext)
{
    if (syncContext->pThreadSem == NULL) {
        co_cond_free((struct stCoCond_t *)syncContext->lwtSem);
    } else {
        free(syncContext->pThreadSem);
    }
    return;
}

void AsyncToSyncCb(SyncContext *syncContext, int32_t ret)
{
    if (syncContext->pThreadSem == NULL) {
        co_cond_signal((struct stCoCond_t *)syncContext->lwtSem);
    } else {
        sem_post((sem_t *)syncContext->pThreadSem);
    }
}

#endif